package com.kun.companion.core.context.impl;

import cn.hutool.core.collection.CollUtil;
import com.kun.companion.core.AbstractApplication;
import com.kun.companion.core.config.ApplicationConfiguration;
import com.kun.companion.core.context.factory.SingletonContextFactory;
import com.kun.companion.core.util.JacksonUtil;
import com.kun.companion.core.util.NewClassGraphUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * 应用程序配置类容器
 * <p>
 * 实现功能：
 * 1. 自动扫描并加载所有{@link ApplicationConfiguration}实现类
 * 2. 根据order值进行优先级排序初始化
 * 3. 提供配置类的单例管理
 * </p>
 *
 * @author gzc
 * @since 2025/1/26
 **/
public class ApplicationConfigurationContext
        implements SingletonContextFactory<Class<? extends ApplicationConfiguration>, ApplicationConfiguration> {
    private static final Logger log = LoggerFactory.getLogger(ApplicationConfigurationContext.class);
    /**
     * 配置类存储容器（线程安全）
     */
    private static final Map<Class<? extends ApplicationConfiguration>, ApplicationConfiguration> CONTEXT
            = new ConcurrentHashMap<>(32);

    @Override
    public synchronized void init(List<String> packagePathList,
                                  Class<? extends AbstractApplication> loader,
                                  Function<String, URL> loadFunction) {
        if (CollUtil.isEmpty(packagePathList)) {
            log.warn("空包路径列表，跳过配置加载");
            return;
        }
        // 扫描所有配置实现类
        List<String> configurationClasses = NewClassGraphUtil
                .findImplement(ApplicationConfiguration.class, packagePathList.toArray(String[]::new));
        log.debug("加载程序配置类 {}", JacksonUtil.toJsonStr(configurationClasses));
        if (CollUtil.isNotEmpty(configurationClasses)) {
            initializeConfigurations(configurationClasses, loader, loadFunction);
        }
//        if (CollUtil.isNotEmpty(configurationClasses)) {
//            // 创建配置类实例并初始化
//            List<ApplicationConfiguration> configurations = new ArrayList<>();
//            for (String className : configurationClasses) {
//                log.debug("加载程序配置类 -> {}", className);
//                Object instance = ClassGraphUtil.newInstance(className);
//                if (instance instanceof ApplicationConfiguration configuration) {
//                    configurations.add(configuration);
//                }
//            }
//
//            // 按照优先级排序
//            configurations.sort(Comparator.comparingInt(ApplicationConfiguration::getOrder));
//
//            // 初始化配置类
//            for (ApplicationConfiguration configuration : configurations) {
//                log.debug("初始化程序配置类 -> {}", configuration.getClass());
//                configuration.init(loader, loadFunction);
//                CONTEXT.put(configuration.getClass(), configuration);
//            }
//            log.info("已初始化程序配置 -> {}", JacksonUtil.toJsonStr(configurationClasses));
//        }
    }

    /**
     * 初始化配置类实例
     */
    private void initializeConfigurations(List<String> configurationClasses,
                                          Class<? extends AbstractApplication> loader,
                                          Function<String, URL> loadFunction) {
        List<ApplicationConfiguration> configurations = new ArrayList<>();

        // 实例化所有配置类
        for (String className : configurationClasses) {
            createConfigurationInstance(className).ifPresent(configurations::add);
        }

        // 按优先级排序后初始化
        if (CollUtil.isNotEmpty(configurations)) {
            configurations.sort(Comparator.comparingInt(ApplicationConfiguration::getOrder));
            configurations.forEach(config -> initSingleConfiguration(config, loader, loadFunction));
            log.info("成功初始化{}个配置类: {}",
                    configurations.size(),
                    JacksonUtil.toJsonStr(configurations.stream()
                            .map(c -> c.getClass().getName())
                            .toList()));
        }
    }

    /**
     * 创建单个配置类实例
     */
    private Optional<ApplicationConfiguration> createConfigurationInstance(String className) {
        try {
            Object instance = NewClassGraphUtil.newInstance(className);
            if (instance instanceof ApplicationConfiguration config) {
                log.debug("已创建配置类实例: {}", className);
                return Optional.of(config);
            }
            log.warn("类[{}]未实现ApplicationConfiguration接口", className);
        } catch (Exception e) {
            log.error("配置类[{}]实例化失败: {}", className, e.getMessage());
        }
        return Optional.empty();
    }

    /**
     * 初始化单个配置类
     */
    private void initSingleConfiguration(ApplicationConfiguration config,
                                         Class<? extends AbstractApplication> loader,
                                         Function<String, URL> loadFunction) {
        try {
            log.debug("正在初始化配置类: {}", config.getClass().getName());
            config.init(loader, loadFunction);
            CONTEXT.put(config.getClass(), config);
        } catch (Exception e) {
            log.error("配置类[{}]初始化失败: {}", config.getClass().getName(), e.getMessage());
        }
    }


    @Override
    public ApplicationConfiguration get(Class<? extends ApplicationConfiguration> cls) {
        if (cls == null) {
            log.warn("查询配置类参数不可为null");
            return null;
        }
        return CONTEXT.get(cls);
    }

    @Override
    public void put(Class<? extends ApplicationConfiguration> key, ApplicationConfiguration value) {
        if (value == null) {
            return;
        }
        Class<? extends ApplicationConfiguration> actualKey = (key != null) ? key : value.getClass();
        CONTEXT.put(actualKey, value);
        log.debug("已手动注册配置类: {}", actualKey.getName());
    }

    @Override
    public void remove(Class<? extends ApplicationConfiguration> cls) {
        if (cls != null && CONTEXT.remove(cls) != null) {
            log.info("已移除配置类: {}", cls.getName());
        }
    }

    @Override
    public void destroy() {
        CONTEXT.clear();
        log.info("已清空所有配置类实例");
    }

    /**
     * 获取所有已加载的配置类
     */
    public static List<ApplicationConfiguration> getAllConfigurations() {
        return new ArrayList<>(CONTEXT.values());
    }
}
